﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using Newtonsoft.Json;
using UCore;
using Microsoft.VisualBasic.Devices;
using System.Text;
using System.Windows.Media.Media3D;
using static UCore.Parsing;
using System.Diagnostics;
using System.Windows.Interop;



namespace Twin {
    public partial class TConsole : Form {

        bool fQuit = false;        
        
        public static List<string> listMsg = new List<string>();
        private static ManualResetEventSlim _resetEvent = new ManualResetEventSlim(false);
        
        public static TextBox txtSnMsg = new TextBox();
        public static TextBox txtSnReceived = new TextBox();
        

        public static String jsonRoot;
        public static String jsonAct;
        public static String jsonDev;
        public static String jsonLcx;
        public static String jsonNvar;
        public static String jsonSl651;
        public static String jsonSta;
        public static String jsonTreg;

        public static String Rfg;

        public static ushort SnMsg = 0;
        public static ushort SnFile = 0;


        public const int COL_INDEX = 0;
        public const int COL_ID = 1;
        public const int COL_UNIT = 4;
        public const int COL_DATA_FMT = 5;
        public const int COL_VALUE = 6;

        private const int BLOCK_PIC = 1024;



        private TabControl tabControlChannelIn;
        private TabControl tabControlDashboard;


        private const int WIDTH_OF_TABTAG = 100;
        private const int HEIGHT_OF_TAB_TAG = 25;

        private const string fn_from_term       = "from_term_uart";
        private const string fn_from_console    = "from_console_uart";

        //Console占用的串口名称
        private string[] serial_physical = new string[] { "COM1", "COM2" };                             //与Console实际占用的串口（含虚拟串口）对应
        private string[] serial_virtual = new string[] { "COM3", "COM5", "COM7", "COM9", "COM11" };     //与Console实际占用的虚拟串口
        private string[] serial_tag      = new string[] { "com1", "com2", "com3", "com4", "com5" };     //与rtu对应


        public List<ListView> list_lvChannelIn = new List<ListView>(); // 用于存储 TextBox 控件的列表

        public static DataGridView dgvCobra = new DataGridView();   // 用于存储Cobra
        public static DataGridView dgvSl651 = new DataGridView();   // 用于存储Sl651
        public static DataGridView dgvInfo = new DataGridView();    // 用于存储Info

        private List<List<string>> llistCobra = new List<List<string>>();
        private List<List<string>> llistSl651 = new List<List<string>>();
        private List<List<string>> llistInfo = new List<List<string>>();


        // 创建Rx对象数组（SIZE_PORTS长度）
        public static Channel[] channel;    // = new Channel[Ini.size_of.port];
        public static Worker[] worker;      // = new Worker[Ini.size_of.port];
        public static XPort[] xport;               // = new XPort[Ini.size_of.port];
        public static ComboBox[] cmbPDrv;          // = new ComboBox[Ini.size_of.port];
        public static CheckBox[] chkBase64;        // = new CheckBox[Ini.size_of.port];
        public static CheckBox[] chkPauseIn;        //暂停from_term_uart处理，便于观察       


        // Add a field to track the active port
        public static int activePort = 3; // Default to com4 (index 3)
        public static int opt_parse = 0;    //G_INFO,G_PROFILE,G_INSTANT,G_DETAIL


        private string[] arg = new string[4];
        //
        private int INST_BITS = 0;
        private int INST_OP = 1;
        private int INST_CMFG = 2;
        //private int INST_INSTANT = 3;


        public TConsole() {
            InitializeComponent();

            
            //
            //tabControlChannelIn.SelectedIndexChanged += tabControlChannelIn_SelectedIndexChanged;   //System.NullReferenceException:“未将对象引用设置到对象的实例
        }


        private void TabbedForm_Load(object sender, EventArgs e) {
            // 获取屏幕工作区的大小
            Size screenSize = Screen.PrimaryScreen.WorkingArea.Size;

            // 计算窗体大小为屏幕工作区大小的 70%
            this.Size = new Size(
                (int)(screenSize.Width * 0.7),
                (int)(screenSize.Height * 0.7)
            );
        }


        // Add a TabControl SelectedIndexChanged event handler
        private void tabControlChannelIn_SelectedIndexChanged(object sender, EventArgs e) {
            activePort = tabControlChannelIn.SelectedIndex;
        }


        private ListView InitializeListView(List<string> col_name) {
            ListView lv = new ListView {
                Dock = DockStyle.Fill,  // 让ListView填满TabPage
                View = View.Details,    // 设置视图为详细信息
                FullRowSelect = true,   // 选择整行
                GridLines = true,       // 显示网格线
                MultiSelect = false     // 只允许选择单个项目
            };

            string name;
            int width;
            for (int i = 0; i < col_name.Count; i++) {
                // 添加列头
                string[] col = col_name[i].Split(',');  //col_name = {name, width}
                name = col[0];
                width = 200;

                if ((col.Length > 1) && (col[1] != null)) {
                    width = int.Parse(col[1]);
                }

                lv.Columns.Add(name, width, HorizontalAlignment.Left); // 添加一个宽度为200的列
            }

            // 注册 listView_Leave 事件处理程序
            lv.Leave += new EventHandler(listView_Leave);

            return lv;
        }


        private void setTab_Channels(ref TabControl tc, ref List<ListView> listViews, int width, int height, int x_off,
            string[] tag_name, List<List<string>> col_names, int defaultTabIndex = 3) {
            
            tc = new TabControl {
                Dock = DockStyle.None,
                Location = new Point(x_off, 0),
                Size = new Size(width, height),
                SizeMode = TabSizeMode.Fixed,
                ItemSize = new Size(WIDTH_OF_TABTAG, HEIGHT_OF_TAB_TAG),
            };

            for (int i = 0; i < Ini.size_of.port; i++) {
                TabPage tp = new TabPage(tag_name[i]);
                tp.Padding = new Padding(5);

                // 1. ListView
                ListView lv = InitializeListView(col_names[i]);
                lv.Dock = DockStyle.Fill;
                lv.Margin = new Padding(0, 0, 0, 35);
                lv.BackColor = Color.Black;
                lv.ForeColor = Color.LightGray;
                //
                tp.Controls.Add(lv);

                // 2. 底部Panel
                Panel controlPanel = new Panel {
                    Dock = DockStyle.Bottom,
                    Height = 30,
                    BackColor = SystemColors.Control,
                    Margin = new Padding(5, 0, 5, 5)
                };

                // 3. 控件布局
                Label lblPassThrough = new Label {
                    Text = "通道驱动：",
                    Location = new Point(60, 7),
                    AutoSize = true
                };

                // ComboBox
                cmbPDrv[i] = new ComboBox {           //此处已初始化
                    DropDownStyle = ComboBoxStyle.DropDownList,
                    Location = new Point(lblPassThrough.Right + 5, 5),
                    Width = 180
                };
                cmbPDrv[i].Items.AddRange(Ini.port_drv);

                //chkBase64
                chkBase64[i] = new CheckBox {
                    Text = "base64编码",
                    Location = new Point(cmbPDrv[i].Right + 40, 5),
                    AutoSize = true
                };


                //chkPauseIn
                chkPauseIn[i] = new CheckBox {
                    Text = "暂停接收",        //处理from_term_uart",
                    Location = new Point(cmbPDrv[i].Right + 150, 5),
                    AutoSize = true
                };


                // 事件绑定
                cmbPDrv[i].SelectedIndexChanged += comboxPDrv_SelectedIndexChanged;
                chkBase64[i].CheckedChanged += chkBase64_CheckedChanged;
                chkPauseIn[i].CheckedChanged += chkPauseIn_CheckedChanged;

                controlPanel.Controls.AddRange(new Control[] {
                    lblPassThrough,
                    cmbPDrv[i],
                    chkBase64[i],
                    chkPauseIn[i]
                });


                // 4. 其他设置保持不变
                tp.Controls.Add(controlPanel);
                tc.TabPages.Add(tp);
                listViews.Add(lv);
                lv.Tag = false;
                lv.MouseClick += (sender, e) => listView_MouseClick(sender, e);

                ContextMenuStrip cms = new ContextMenuStrip();
                cms.Items.Add("copy msg", null, (sender1, e1) => Option1_Click(sender1, e1, lv));
                cms.Items.Add("clear all msgs", null, (sender1, e1) => Option2_Click(sender1, e1, lv));
                lv.ContextMenuStrip = cms;

                if (defaultTabIndex >= 0 && defaultTabIndex < tc.TabPages.Count) {
                    tc.SelectedIndex = defaultTabIndex;
                }
            }
        }


        // 新的事件处理方法
        private void comboxPDrv_SelectedIndexChanged(object sender, EventArgs e) {
            ComboBox combo = sender as ComboBox;
            // 获取当前选项值
            string selectedMode = combo.SelectedItem.ToString();
        }


        //copy msg
        private void Option1_Click(object sender, EventArgs e, ListView lv) {
            if (lv == null) return;

            // 获取鼠标在ListView上的坐标
            Point pt = lv.PointToClient(new Point(Control.MousePosition.X, Control.MousePosition.Y));
            ListViewHitTestInfo hitTest = lv.HitTest(pt);

            ListViewItem.ListViewSubItem clickedSubItem = hitTest.SubItem;
            if (clickedSubItem == null) return;

            string content = clickedSubItem.Text;
            txtRawMsg.Text = content;
        }


        private void Option2_Click(object sender, EventArgs e, ListView lv) {
            if (lv == null) return;
            lv.Items.Clear();
        }


        private void setTab_DataGridView(ref TabControl tc, ref DataGridView dgv, string tag_name, List<string> col_name) {
            TabPage tp = new TabPage(tag_name);
            tp.Name = tag_name;
            
            dgv = InitDataGridView(col_name);

            SetDarkTheme(dgv);
            //SetDarkTheme(dgvSl651);

            tp.Controls.Add(dgv);
            tc.TabPages.Add(tp);
        }



        private DataGridView InitDataGridView(List<string> col_names) {
            DataGridView dgv = new DataGridView {
                Dock = DockStyle.Fill,                                                          // 让DataGridView填满TabPage
                AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None,                     // 自动调整列宽以适应内容
                ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize, // 自动调整列头大小
                MultiSelect = false,                                                            // 只允许选择单个项目
                SelectionMode = DataGridViewSelectionMode.FullRowSelect,                        // 选择整行
                //GridLineStyle = DataGridViewLineStyle.Solid, // 显示网格线
                RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing   // 禁止调整行头大小
            };

            foreach (string col in col_names) {
                string[] colInfo = col.Split(','); // col_names："ColumnName,Width"
                string name = colInfo[0];
                int width = 200; // 默认列宽

                if (colInfo.Length > 1 && !string.IsNullOrEmpty(colInfo[1])) {
                    width = int.Parse(colInfo[1]);
                }

                // 添加列
                DataGridViewColumn column = new DataGridViewTextBoxColumn {
                    Name = name,
                    HeaderText = name,
                    Width = width,
                    DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleLeft } // 设置列内容左对齐
                };
                dgv.Columns.Add(column);
            }

            // 注册 DataGridView 的事件处理程序
            dgv.CellClick += new DataGridViewCellEventHandler(dgv_CellClick);
            dgv.CellDoubleClick += new DataGridViewCellEventHandler(dgv_CellDoubleClick);

            return dgv;
        }



        private void showOption(XPort xport, string content) {
            int iChip = UI.init_cmbChipSel(cmbChip, Ini.chip);

            string[] inst = content.Split(',');
            string sOp = inst[1];

            switch (sOp) {
                case "OP_RD_AREA":          //OP_RD_AREA, [cmfg], 00[area_name]
                    frmRdArea optionRdArea = new frmRdArea(xport, content, iChip);   
                    //optionRdArea.ShowDialog();
                    optionRdArea.Show();
                    return;
                //break;

                case "OP_RD_BLOC":          //OP_RD_BLOC, [cmfg], 00[area_name]
                    frmRdBloc optionRdBloc = new frmRdBloc(xport, content, iChip);
                    //optionRdBloc.ShowDialog();
                    optionRdBloc.Show();
                    return;

                case "OP_WR_AREA":          //OP_WR_AREA, [cmfg], 1[i_area], [area_sn] 		[kvs:k0=v0>k1=v1>kn=vn] 
                    frmWrArea optionWrArea = new frmWrArea(xport, content, iChip);   
                    optionWrArea.Show();
                    return;
                    //break;

                case "OP_WR_BLOC":          //OP_WR_BLOC, [cmfg], 1[i_bloc],[addr],[hex]
                    frmWrBloc optionWrBloc = new frmWrBloc(xport, content, iChip);
                    optionWrBloc.Show();
                    return;
                    //break;

                case "OP_RD_BELT":          //OP_RD_BELT, [cmfg], [i_fmt]
                    frmRdBelt optionRdBelt = new frmRdBelt(xport, content);   
                    optionRdBelt.Show();
                    return; 
                    //break;

                case "OP_RD_INS":           //OP_RD_INS, [cmfg], [instant_fmt]
                    frmRdIns optionRdInstant = new frmRdIns(xport, content);   
                    optionRdInstant.Show();
                    return;

                case "OP_RD_ELEM":           //OP_RD_ELEM, [cmfg], [i_elem], [dt], [step]
                    frmRdElem optionRdElem = new frmRdElem(xport, content);
                    optionRdElem.Show();
                    return;

                case "OP_WR_ELEM":           //OP_WR_ELEM, [cmfg], [i_elem], [dt], [step]
                    frmWrElem optionWrElem = new frmWrElem(xport, content);
                    optionWrElem.Show();
                    return;

                case "OP_RD_REC":           //OP_RD_REC, [cmfg], 180305073F0A[dt]
                    frmRdRec optionRdRec = new frmRdRec(xport, content);
                    optionRdRec.Show();
                    return;
                

                case "OP_SET_DT_FORCE":
                case "OP_SET_DT_NOTIFY":
                    frmDT optionDT = new frmDT(xport, content);   
                    optionDT.Show();
                    return;

                case "OP_SET_FACTORY":
                case "OP_SET_RESTART":
                case "OP_SET_MONITOR_THIS":
                case "OP_INST_EXEC":
                case "OP_INST_SL651":
                case "OP_INST_REMOTE":
                case "MSG_GLASS":
                    frmMisc optionMisc = new frmMisc(xport, content);   
                    optionMisc.Show();
                    return; 
                    //break;


                default: break;
            }
            //return content;
        }

        //private static ushort getSnMsg() {

        //    Ini.ReadKeyValue(Ini.iniFilePath, "Info.MsgSn", "0x" + sHex);

        //}


        private static ushort incSnMsg() { 
            SnMsg++;
            string sHex = SnMsg.ToString("X");  // 例如 0x22
            Ini.WriteKeyValue(Ini.path_Console_ini, "Info.MsgSn", "0x" + sHex);
            return SnMsg;
        }


        public static void sendAsProtocol(XPort xport, ref CInfo cInfo, string wr_kvs, string protocol_name) {
            cInfo.sMsgIndex = Convert.ToString(incSnMsg());

            string[] sInst = Msg.MakeInst_cobra(ref cInfo, wr_kvs);
            if ((sInst == null) || (sInst[0] == "")) {
                MessageBox.Show("Error: Inst == null ");
                return;
            }
            //coverWithProtcol(sInst, protocol_name);
            writeToPort(xport, sInst, protocol_name);
        }


        // dgv_CellClick单元格单击 事件处理
        private void dgv_CellClick(object sender, DataGridViewCellEventArgs e) {
            TabPage selectedTab = this.tabControlDashboard.SelectedTab; // 获取当前选中的TabPage

            // 检查是否有选中的TabPage
            if (selectedTab != null && e.RowIndex >= 0 && e.ColumnIndex >= 0){
                // 获取当前单元格的内容
                int iCol;
                string name = selectedTab.Name;
                
                switch (name) {
                    case "cobra":
                        string bits = dgvCobra.Rows[e.RowIndex].Cells[1].Value.ToString();
                        string args = dgvCobra.Rows[e.RowIndex].Cells[2].Value.ToString();
                        string currentContent = bits + "," + args;
                        xport[activePort].is_base64 = chkBase64[activePort].Checked;
                        //
                        showOption(xport[activePort], currentContent);
                        break;

                    case "sl651":
                        iCol = 1;
                        string s = Common.GetSelectedRowValue(dgvSl651, iCol);
                        //sInst = makeInst_sl651(sPara, sBits);
                        break;
                }

            } else {
                System.Console.WriteLine("没有选中的TabPage。");
                return;
            }
        }


        private static void setTxt(TextBox txtBox, string[] arr) {
            string s = "";
            for (int i = 0; i < s.Length; i++) {
                s += arr[i];
                if (i < (s.Length - 1)) {
                    s += "\r\n";
                }
            }
            txtBox.Text = s;
        }


        //"! ... _"
        /*private static void coverWithProtcol(string[] sInst, string name) {
            switch (name) {
                case "cobra":
                    for (int i = 0; i < sInst.Length; i++) {
                        sInst[i] = "!" + sInst[i] + "_";
                    }
                    break;
                case "sl651":
                    break;
                default: break;
            }
        }*/


        // 处理单元格双击事件
        private void dgv_CellDoubleClick(object sender, DataGridViewCellEventArgs e) {
            
        }


        // 事件处理程序，你需要根据实际情况来实现
        private void drvCobra_MouseClick(object sender, MouseEventArgs e) {
            DataGridView dgv = sender as DataGridView;
            if (dgv != null) {
                // 处理点击事件
            }
        }

        private void drvSl651_MouseClick(object sender, MouseEventArgs e) {
            DataGridView dgv = sender as DataGridView;
            if (dgv != null) {
                // 处理点击事件
            }
        }

        private void drvInfo_MouseClick(object sender, MouseEventArgs e) {
            DataGridView dgv = sender as DataGridView;
            if (dgv != null) {
                // 处理点击事件
            }
        }


        private void initUI_Channels() {

            //xport = new XPort[Ini.size_of.port];
            
            // 获取屏幕工作区的大小
            Size screenSize = Screen.PrimaryScreen.WorkingArea.Size;

            // 计算窗体大小为屏幕工作区大小的 70%
            /*this.Size = new Size(
                (int)(screenSize.Width * 0.7),
                (int)(screenSize.Height * 0.8)
            );*/

            int heightStatus = stripStatus.Height;

            // 设置TabControl的宽度为Form宽度的一半
            int width = this.Size.Width / 2;
            int height = (Height - heightStatus) / 2 - HEIGHT_OF_TAB_TAG;    // - 25;


            //left
            int x_off_left = 0;
            //string[] serial_tag = new string[] { "com1", "com2", "com3", "com4", "com5" };
            // 静态初始化List<List<string>>
            var col_names_left = new List<List<string>> {
                new List<string> { "dt,350", "msgs,400" },       //400:宽度
                new List<string> { "dt,350", "msgs,400" },
                new List<string> { "dt,350", "msgs,400" },
                new List<string> { "dt,350", "msgs,400" },
                new List<string> { "dt,350", "msgs,400" }
            };

            setTab_Channels(
                ref tabControlChannelIn, 
                ref list_lvChannelIn, 
                width, 
                height, 
                x_off_left, 
                serial_tag, 
                col_names_left, 
                3
            );

            // Now that tabControlChannelIn is initialized, add the event handler
            tabControlChannelIn.SelectedIndexChanged += tabControlChannelIn_SelectedIndexChanged;

            this.Controls.Add(this.tabControlChannelIn);
        }


        private void listView_MouseClick(object sender, MouseEventArgs e) {
            if (sender is ListView) {

                ListView lv = sender as ListView;
                if (lv == null) return;

                // 获取点击的项和子项
                ListViewHitTestInfo hitTest = lv.HitTest(e.X, e.Y);
                ListViewItem clickedItem = hitTest.Item;
                ListViewItem.ListViewSubItem clickedSubItem = hitTest.SubItem;

                if (clickedItem == null) return;
                if (clickedSubItem == null) return;

                if (e.Button == MouseButtons.Left) {
                    bool f = (bool)lv.Tag;

                    lv.Tag = !f;

                    // 高亮显示点击的行
                    clickedItem.Selected = true;
                    lv.FocusedItem = clickedItem;
                    lv.EnsureVisible(clickedItem.Index);

                    // 选中点击的单元格
                    //int subItemIndex = clickedSubItem.Index;
                    lv.EnsureVisible(clickedItem.Index);
                    lv.SelectedItems.Clear(); // 清除之前的选中状态
                    clickedItem.Selected = true; // 设置当前行为选中状态
                    lv.SelectedItems[0].Selected = true; // 确保选中的是点击的行
                    lv.SelectedItems[0].Focused = true; // 设置焦点到选中的行
                    //lv.SelectedItems[0].SubItems[subItemIndex].Focused = true; // 设置焦点到点击的单元格

                    // 允许复制粘贴
                    lv.LabelEdit = true; // 允许编辑
                    lv.MultiSelect = false; // 只允许选中一个单元格

                    //}
                } /*else if (e.Button == MouseButtons.Right) {
                    //string columnHeaderText = lv.Columns[clickedSubItem..Index].Text;
                    //if (columnHeaderText == "msgs") {
                        string content = clickedSubItem.Text;
                        txtRawMsg.Text = content;
                    //}
                }*/
            }
        }

        private void listView_Leave(object sender, EventArgs e) {
            ListView lv = sender as ListView;

            // 获取点击的项
            if (lv != null) {
                lv.Scrollable = true;
            }
        }



        //回差截取字符串尾部
        public string hysteresisTail(string input, int trig_limit) {
            // 如果字符串长度小于或等于请求的字符数，则返回整个字符串
            if (input.Length <= trig_limit) {
                return input;
            }
            // 否则，截取字符串的后 x 个字符
            else {
                return input.Substring(input.Length - trig_limit / 2);
            }
        }


        private List<List<string>> Dictionary_to_llist(Dictionary<string, Dictionary<string, string>> iniDictionary, string section) {
            List<List<string>> dataList = new List<List<string>>();

            if (iniDictionary.ContainsKey(section)) {
                var kvps = iniDictionary[section];
                foreach (var kvp in kvps) {
                    List<string> rowData = new List<string> { kvp.Key };
                    string s = kvp.Value.ToString();
                    var item = s.Split('|');

                    /*if (item.Length == 2) {
                        rowData.Add(item[0].Trim());
                        rowData.Add(item[1].Trim());
                    } else {
                        rowData.Add(s.Trim());
                    }*/

                    //rowData.Add(kvp.Key);

                    for (int i = 0; i < item.Length; i++) {
                        rowData.Add(item[i].Trim());
                    }
                    
                    dataList.Add(rowData);
                }
            } else {
                System.Console.WriteLine($"未找到节：{section}");
            }

            return dataList;
        }


        private void read_Console_ini() {
            // 读取INI文件并填充字典
            Ini.ReadIniFile(Ini.iniDictionary, Ini.path_Console_ini);
        }


        private void initFrom_ConsoleIni() {
            // 读取INI文件并填充字典
            //Ini.ReadIniFile(Ini.iniDictionary, Ini.path_Console_ini);

            // 获取指定节点下的所有键值对
            string sectionName;

            sectionName = "InstCobra";
            llistCobra = Dictionary_to_llist(Ini.iniDictionary, sectionName);


            // 获取指定节点下的所有键值对
            sectionName = "Inst651";
            llistSl651 = Dictionary_to_llist(Ini.iniDictionary, sectionName);


            // 获取指定节点下的所有键值对
            sectionName = "Info";
            llistInfo = Dictionary_to_llist(Ini.iniDictionary, sectionName);
        }


        private void SetDarkTheme(DataGridView dgv) {
            dgv.DefaultCellStyle.BackColor = Color.Black;
            dgv.DefaultCellStyle.ForeColor = Color.LightGray;   // White;
            dgv.ColumnHeadersDefaultCellStyle.BackColor = Color.Black;
            dgv.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
            dgv.RowHeadersDefaultCellStyle.BackColor = Color.Black;
            dgv.RowHeadersDefaultCellStyle.ForeColor = Color.White;
            dgv.GridColor = Color.White;
        }

        
        private void initUI_Dashboard() {

            int heightStatus = stripStatus.Height;
            //
            int width = Size.Width / 2;
            int height = (Height - heightStatus) / 2 - HEIGHT_OF_TAB_TAG;
            int y_off = height;
            string[] tag_name = new string[] { "cobra", "sl651", "info", "透明" };


            // 静态初始化List<List<string>>
            var col_name = new List<List<string>> {
                new List<string> { "title,150", "bits,50", "args,260", "data" },
                new List<string> { "op,100", "inst,495" },
                new List<string> { "name", "v", "memo" }
            };


            tabControlDashboard = new TabControl {
                Dock = DockStyle.None,          // 不填充整个Form
                Location = new Point(0, y_off), // 设置TabControl的位置
                Size = new Size(width, height), // 设置TabControl的大小
                SizeMode = TabSizeMode.Fixed,
                ItemSize = new Size(WIDTH_OF_TABTAG, HEIGHT_OF_TAB_TAG), // 标签大小
                Alignment = TabAlignment.Bottom
            };


            setTab_DataGridView(ref tabControlDashboard, ref dgvCobra, tag_name[0], col_name[0]);
            setTab_DataGridView(ref tabControlDashboard, ref dgvSl651, tag_name[1], col_name[1]);
            setTab_DataGridView(ref tabControlDashboard, ref dgvInfo, tag_name[2], col_name[2]);


            // 为DataGridView添加MouseClick事件监听器
            dgvCobra.MouseClick += (sender, e) => {
                drvCobra_MouseClick(sender, e);
            };

            dgvSl651.MouseClick += (sender, e) => {
                drvSl651_MouseClick(sender, e);
            };

            dgvInfo.MouseClick += (sender, e) => {
                drvInfo_MouseClick(sender, e);
            };

            //init_datas();
            data_to_dgvCobra();
            data_to_dgvSl651();
            data_to_dgvInfo();
            //data_to_glass();

            //发送序号MsgSn
            txtSnMsg.Text = Ini.iniDictionary["Info"]["MsgSn"];
            
            this.Controls.Add(this.tabControlDashboard);
        }


        private void data_to_dgvCobra() {
            foreach (List<string> rowData in llistCobra) {
                dgvCobra.Rows.Add(rowData.ToArray());
            }
        }

        private void data_to_dgvSl651() {
            foreach (List<string> rowData in llistSl651) {
                dgvSl651.Rows.Add(rowData.ToArray());
            }
        }


        private void data_to_dgvInfo() {
            foreach (List<string> rowData in llistInfo) {
                dgvInfo.Rows.Add(rowData.ToArray());
            }
        }


        private void data_to_glass() {
        }


        private void initPorts() {
            for (int iPort = 0; iPort < Ini.size_of.port; iPort++) {
                initPort(iPort);
            }
        }


        private void initPort(int i) {
            btnClearBuf.Enabled = false;

            xport[i] = new XPort();
            xport[i].iPort = i;
            
            int iPDrv = abs_getV("dev.LPort.Port[" + i.ToString() + "].pdrv", map_abs["absDEV"]);
            if (iPDrv < 0) {
                MessageBox.Show("Error: bad map absDEV.");
                Application.Exit();
            }
            xport[i].port_type = iPDrv;
            cmbPDrv[i].SelectedIndex = iPDrv;

            int baudrate;
            if (iPDrv == Ini.PORT_FILE) {
                btnClearBuf.Enabled = true;
            } else if ((iPDrv == Ini.PORT_SERIAL_PHYSICAL) || (iPDrv == Ini.PORT_SERIAL_VIRTUAL)) {
                xport[i].field = new Serial();
                xport[i].field.GetPortsUI();      //重新显示全部物理串口
                baudrate = abs_getV("dev.LPort.Port[3].Baudrate", map_abs["absDEV"]);
                //
                switch (iPDrv) {
                    case Ini.PORT_SERIAL_PHYSICAL:
                        xport[i].field.OpenPort(serial_physical[i], baudrate);      //打开物理串口
                        break;
                    case Ini.PORT_SERIAL_VIRTUAL:
                        xport[i].field.OpenPort(serial_virtual[i], baudrate);       //打开虚拟串口
                        break;
                }
            }
        }


        private void initUI() {
            this.Size = new Size(this.Width, this.Height);

            //最新发送序号，txtSnMsg
            txtSnMsg.Location = new System.Drawing.Point(850, 728);
            txtSnMsg.Name = "txtSnMsg";
            txtSnMsg.Size = new System.Drawing.Size(72, 21);
            txtSnMsg.TabIndex = 75;
            Controls.Add(txtSnMsg);
            //SnMsg = ini
            txtSnMsg.Text = SnMsg.ToString();


            //最新接收序号，txtSnReceiveded
            txtSnReceived.Location = new System.Drawing.Point(850, 670);
            txtSnReceived.Name = "txtSnReceiveded";
            txtSnReceived.Size = new System.Drawing.Size(72, 21);
            txtSnReceived.TabIndex = 75;
            Controls.Add(txtSnReceived);



            //Parse option
            optInfo.Checked = true;

            //txtRawMsg
            txtRawMsg.ForeColor = System.Drawing.Color.Black;
            txtRawMsg.Multiline = true;
            txtRawMsg.ScrollBars = ScrollBars.Vertical;
            txtRawMsg.TextChanged += TxtRawMsg_TextChanged;

            //txtExplicit
            txtExplicit.ForeColor = System.Drawing.Color.Black;
            txtExplicit.ScrollBars = ScrollBars.Vertical;

            labelProgress.Text = "";
        }


        private void TxtRawMsg_TextChanged(object sender, EventArgs e) {
            string[] t = Worker.split_and_clean(txtRawMsg.Text);
            //Rx.MergeProcess(t);
            //throw new NotImplementedException();
        }


        private void SensorMonitor_Load(object sender, EventArgs e) {
            FormBorderStyle = FormBorderStyle.FixedSingle; // 设置窗体边框样式为固定单线框
            MaximizeBox = false;   // 移除最大化按钮
            MinimizeBox = false;   // 禁止调整大小

            //Area.ini
            read_Area_ini();
            Parsing.initFromIni();

            //Console.ini
            read_Console_ini();
            initFrom_ConsoleIni();

            channel = new Channel[Ini.size_of.port];
            worker = new Worker[Ini.size_of.port];
            xport = new XPort[Ini.size_of.port];
            cmbPDrv = new ComboBox[Ini.size_of.port];
            chkBase64 = new CheckBox[Ini.size_of.port];
            chkPauseIn = new CheckBox[Ini.size_of.port];


            initUI();
            initUI_Channels();
            initUI_Dashboard();

            initPorts();

            //接收线程
            for (int iPort = 0; iPort < Ini.size_of.port; iPort++) {
                list_lvChannelIn[iPort].Tag = false;
                //
                channel[iPort] = new Channel(iPort);      
                worker[iPort] = new Worker(fQuit, iPort, this);
            }

            this.Show();
        }


        // 方法：将窗体定位到屏幕右上方
        public static void PositionFormAtTopRight(Form form) {
            // 获取主屏幕的工作区
            Screen screen = Screen.PrimaryScreen;
            Rectangle workingArea = screen.WorkingArea;

            // 计算窗体的新位置
            Point newLocation = new Point {
                X = workingArea.Right - form.Width,
                Y = workingArea.Top
            };

            // 设置窗体的新位置
            form.Location = newLocation;
        }


        public void styleJson(string json) {
            // 格式化JSON字符串
            dynamic parsedJson = JsonConvert.DeserializeObject(json);
            string formattedJson = JsonConvert.SerializeObject(parsedJson, Formatting.Indented);

            Action updateTextbox = () => {
                txtExplicit.Text = formattedJson;
            };

            // 在 UI 线程上执行更新操作
            if (txtExplicit.InvokeRequired) {
                txtExplicit.BeginInvoke(updateTextbox);
            } else {
                //updateTextbox();
                txtExplicit.Text = formattedJson;
            }
        }


        private static void writeToPort(XPort xPort, string[] inst, string protocol_name) {
            switch(xPort.port_type) {
                case Ini.PORT_SERIAL_PHYSICAL:
                case Ini.PORT_SERIAL_VIRTUAL:
                    write_Field(xPort, inst, protocol_name);
                    break;

                case Ini.PORT_FILE:
                    write_File(xPort, inst, protocol_name);
                    break;
            }
        }

        private static void transmitMsg(XPort xport, string msg, string protocol_name) {
            switch (protocol_name) {
                case "cobra":
                    xport.field.SendDataString("!");
                    xport.field.SendDataString(msg);       // 调用SendDataBinary发送数据
                    xport.field.SendDataString("_");
                    break;
                case "sl651":
                    break;
                default: break;
            }
        }


        private static string data_encode(string inst, bool is_base64, string protocol_name) {
            string str;
            byte[] data = Common.Hex2Array(inst);         // 将字符串转换为ASCII字节数组

            //base64 ?
            if (is_base64) {
                str = HBase64.Encode(data);     //hbase64
            } else {
                str = inst;    //"49..."
            }

            //protocol
            switch (protocol_name) {
                case "cobra":
                    str = "!" + str + "_";
                    break;
            }

            return str;
        }


        //写field-port
        private static void write_Field(XPort xport, string[] inst, string protocol_name) {
            string str64;
            
            for (int i = 0; i < inst.Length; i++) {
                str64 = data_encode(inst[i], xport.is_base64, protocol_name);
                transmitMsg(xport, str64, protocol_name);
            }            
        }


        private static void write_File(XPort xport, string[] inst, string protocol_name) {
            string fname = Ini.get_dir_io_file() + "\\" + fn_from_console + (xport.iPort + 1).ToString() + ".txt";
            
            //连在一起
            string insts = "";
            for (int i = 0; i < inst.Length; i++) {
                //insts += inst[i];
                insts += data_encode(inst[i], xport.is_base64, protocol_name);
            }

            while (true) {
                try {
                    File.WriteAllText(fname, insts);    //自动关闭
                    break;
                } catch (Exception e) {
                    System.Console.WriteLine(e.ToString());
                }

                Thread.Sleep(1000);
            }
        }


        private void btnQuit_Click(object sender, EventArgs e) {

            //for 4 sreial-in
            for (int i = 0; i < Ini.size_of.port; i++) {
                channel[i].set_fQuit(true);
                worker[i].set_fQuit(true);
            }

            //for 1) msg parsing; 2) msg rxing
            _resetEvent.Set();
            fQuit = true;

            Application.Exit();
        }


        private void panel2_Paint(object sender, PaintEventArgs e) {

        }

        private void panel1_Paint(object sender, PaintEventArgs e) {

        }


        private void btnREAD_ALL_FILES_Click(object sender, EventArgs e) {

            CInfo cInfo = new CInfo();

            cInfo.sOpArgs = "OP_RD_AREA,,";
            string bits = "0003";
            Msg.setInfo_bits(ref cInfo, bits);

            string s = "OP_RD_AREA,,"; 
            if (Parsing.area_name.Length <= 0) return;

            string[] sInst;
            //XPort xport = new XPort();
            xport[activePort].port_type = Ini.PORT_FILE;

            for (int j = 1; j >= 0; j--) {                              //"m", "v"
                for (int i = 0; i < Parsing.area_name.Length; i++) {
                    cInfo.sOpArgs = s + j.ToString() + i.ToString();
                    cInfo.sMsgIndex = Convert.ToString(++SnMsg);
                    //staSnMsg.Text = "SnMsg:" + SnMsg.ToString().PadLeft(6, ' ');
                    // 使用Invalidate方法
                    //staSnMsg.Invalidate();
                    //
                    sInst = Msg.m_dll.doMakeMsg(cInfo);
                    //coverWithProtcol(ref sInst, "cobra");
                    //xport[activePort].iPort = cmbTxPort.SelectedIndex;
                    writeToPort(xport[activePort], sInst, "cobra");
                    //Thread.Sleep(1000);
                }
            }
        }

        private void btnSqlite_Click(object sender, EventArgs e) {
            //UCore.Sqlite.test_sqlite3();
        }

        private void stripStatus_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {

        }


        private void btnClearBuf_Click(object sender, EventArgs e) {
            string sComN = (activePort + 1).ToString();
            string fname = Ini.get_dir_io_file() + "\\" + fn_from_console + sComN + ".txt";
                try {
                    File.WriteAllText(fname, "");    //自动关闭
                    MessageBox.Show("com" + sComN + "发送缓冲被清空了！");    
                } catch (Exception ex) {
                    System.Console.WriteLine(ex.ToString());
                }
        }

        
        private void cmbTxPort_SelectedIndexChanged(object sender, EventArgs e) {

        }


        private void chkBase64_CheckedChanged(object sender, EventArgs e) {
            //xport[activePort].base64 = chkBase64.Checked;
        }


        //暂停/恢复 接收
        private void chkPauseIn_CheckedChanged(object sender, EventArgs e) {
            if (chkPauseIn[activePort].Checked) {
                channel[activePort].set_fPause(true);
            } else {
                channel[activePort].set_fPause(false);
            }
        }


        private void btnRemote_Click(object sender, EventArgs e) {
            //执行Remote = 0003 | OP_INST_REMOTE, [cmfg], 1[i_btn]
            string currentContent = "0003,OP_INST_REMOTE,,";
            frmOled oled = new frmOled(xport[activePort], currentContent);
            oled.Show();
        }

        private void btnMemViewer_Click(object sender, EventArgs e) {
            BinView bin_view = new BinView(Ini.M_MEM, xport[activePort]);
            bin_view.Show();
        }

        private void btnMassViewer_Click(object sender, EventArgs e) {
            BinView bin_view = new BinView(Ini.M_MASS, xport[activePort]);
            bin_view.Show();
        }

        private void btnTwinQuit_Click(object sender, EventArgs e) {
            CInfo cInfo = new CInfo();

            arg[INST_BITS] = "0003";
            arg[INST_OP] = "OP_INST_TWIN_PAUSE";
            arg[INST_CMFG] = "";
            
            Msg.setInfo_bits(ref cInfo, arg[INST_BITS]);

            cInfo.sOpArgs = arg[INST_OP] + "," + arg[INST_CMFG];
            string wr_kvs = "";

            TConsole.sendAsProtocol(xport[activePort], ref cInfo, wr_kvs, "cobra");
        }
    }
}
